﻿/*在终端打印信息*/
#ifndef DPRINTER_HPP
#define DPRINTER_HPP

#include "../HDBase/DList.hpp"
#include "../HDMemory/DSharedPointer.hpp"
#include "../HDBase/DString.hpp"
#include <iostream>
// #include <QDebug>

#define OUT_STREAM std::cout
// #define OUT_STREAM qDebug().noquote().nospace()
#define DEND '\n'


class DPrinter
{
public:
	DPrinter();
	DPrinter& noEndLine();
	DPrinter& nospace();

	explicit DPrinter(bool b) {*this << b;}
	explicit DPrinter(int i) {*this << i;}
	explicit DPrinter(unsigned int ui) {*this << ui;}
	explicit DPrinter(short sh) {*this << sh;}
	explicit DPrinter(unsigned short ush) {*this << ush;}
	explicit DPrinter(long l) {*this << l;}
	explicit DPrinter(unsigned long ul) {*this << ul;}
	explicit DPrinter(long long ll) {*this << ll;}
	explicit DPrinter(unsigned long long ull) {*this << ull;}
	explicit DPrinter(float f) {*this << f;}
	explicit DPrinter(double d) {*this << d;}
	explicit DPrinter(long double ld) {*this << ld;}
	explicit DPrinter(char c) {*this << c;}
	explicit DPrinter(unsigned char uc) {*this << uc;}
	explicit DPrinter(const char* s) {*this << s;}
	explicit DPrinter(void* p) {*this << p;}
	explicit DPrinter(const DString& str) {*this << str;}
	template <class T>
	explicit DPrinter(const DListNode<T>& node) {*this << node;}
	template <class T>
	explicit DPrinter(const DList<T>& list) {*this << list;}
	template <class T>
	explicit DPrinter(const DSharedPointer<T>& pointer) { *this << pointer; }
	~DPrinter() = default;

	DPrinter& operator<<(bool b);
	DPrinter& operator<<(int i);
	DPrinter& operator<<(unsigned int ui);
	DPrinter& operator<<(short sh);
	DPrinter& operator<<(unsigned short ush);
	DPrinter& operator<<(long l);
	DPrinter& operator<<(unsigned long ul);
	DPrinter& operator<<(long long ll);
	DPrinter& operator<<(unsigned long long ull);
	DPrinter& operator<<(float f);
	DPrinter& operator<<(double d);
	DPrinter& operator<<(long double ld);
	DPrinter& operator<<(char c);
	DPrinter& operator<<(unsigned char uc);
	DPrinter& operator<<(const char* s);
	DPrinter& operator<<(void* p);
	DPrinter& operator<<(const DString& str);
	template <class T>
	DPrinter& operator<<(const DListNode<T>& node);
	template <class T>
	DPrinter& operator<<(const DList<T>& list);
	template <class T>
	DPrinter& operator<<(const DSharedPointer<T>& pointer);

private:
	char* endLine_;
	char haveSpace_;
};

/********************************* 实现 *********************************/

DPrinter::DPrinter()
	: haveSpace_(true)
{
	endLine_ = new char[2];
	endLine_[0] = DEND;
	endLine_[1] = '\0';
}

DPrinter& DPrinter::noEndLine()
{
	if (nullptr != endLine_)
		delete[] endLine_;
	endLine_ = new char[1];
	endLine_[0] = '\0';
	return *this;
}


DPrinter& DPrinter::nospace()
{
	haveSpace_ = false;
	return *this;
}

DPrinter& DPrinter::operator<<(bool b)
{
	OUT_STREAM << b << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(int i)
{
	OUT_STREAM << i << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(unsigned int ui)
{
	OUT_STREAM << ui << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(short sh)
{
	OUT_STREAM << sh << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(unsigned short ush)
{
	OUT_STREAM << ush << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(long l)
{
	OUT_STREAM << l << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(unsigned long ul)
{
	OUT_STREAM << ul << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(long long ll)
{
	OUT_STREAM << ll << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(unsigned long long ull)
{
	OUT_STREAM << ull << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(float f)
{
	OUT_STREAM << f << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(double d)
{
	OUT_STREAM << d << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(long double ld)
{
	OUT_STREAM << ld << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(char c)
{
	OUT_STREAM << c << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(unsigned char uc)
{
	OUT_STREAM << uc << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(const char* s)
{
	OUT_STREAM << s << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(void* p)
{
	OUT_STREAM << p << endLine_;
	return *this;
}

DPrinter& DPrinter::operator<<(const DString& str)
{
	*this << str.data_ << endLine_;
	return *this;
}

template <class T>
DPrinter& DPrinter::operator<<(const DListNode<T>& node)
{
	*this << "DNode( data_:" << node.data_ << " )";
	return *this;
}

template <class T>
DPrinter& DPrinter::operator<<(const DList<T>& list)
{
	char* oldEndLine = endLine_;
	endLine_ = "";
	if (list.isEmpty())
	{
		*this << "DList()";
		return *this;
	}

	*this << "DList(";
	for (auto it = list.begin(); it != DListIterator<T>(list.last_); ++it)
		*this << *it << ", ";
	*this << list.last() << ')' << oldEndLine;
	endLine_ = oldEndLine;

	return *this;
}

template <class T>
DPrinter& DPrinter::operator<<(const DSharedPointer<T>& pointer)
{
	*this << "DSharedPointer( data:" << *pointer.data_ << ", useCount:" << *pointer.count_ << " )";
	return *this;
}

#endif  // DPRINTER_HPP
